package mux

import (
	"fmt"
	"log"
	"runtime"
	"time"

	"context"

	logx "xp/lib/log"
)

const (
	maxHandlerTime            = 10 * time.Second
	panicStacktraceBufferSize = 1 << 10
)

func NewPanicRecover(panicHandler Handler) Middleware {
	return func(next Handler) Handler {
		return func(ctx *Ctx) {
			defer func() {
				if v := recover(); v != nil {
					logx.Warn("req_id", ctx.reqID, "panic", fmt.Sprint(v))
					if panicHandler != nil {
						panicHandler(ctx)
					}
					buf := make([]byte, panicStacktraceBufferSize)
					buf = buf[:runtime.Stack(buf, false)]
					ctx.stacktrace = buf
					log.Printf("panic recover: %v\n%s", v, buf)
				}
			}()
			next(ctx)
		}
	}
}

func int64FromBytes(b []byte) int64 {
	var n int64
	for i := 0; i < len(b); i++ {
		if b[i] < '0' || b[i] > '9' {
			return 0
		}
		n *= 10
		n += int64(b[i] - '0')
	}
	return n
}

func Context(next Handler) Handler {
	return func(req *Ctx) {
		ctx := context.Background()
		ctx, _ = context.WithDeadline(ctx, req.Time().Add(maxHandlerTime))
		req.SetContext(ctx)
		next(req)
	}
}
